home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
screen
/
blank.arc
/
BLANK.ASM
next >
Wrap
Assembly Source File
|
1989-04-20
|
33KB
|
733 lines
PAGE 60,132
NAME Blank
.MODEL Small
.CODE
GoInt MACRO Num ; Quick And Dirty
IF ((.TYPE Num) AND 4)
Int Num ; INT for constants
Iret
ELSE
Jmp SHORT Num ; Jump to address
Nop ; Align
ENDIF
ENDM
Inp MACRO Reg, Port ; Used to FORCE a delay after I/O
In Reg, Port
Jmp SHORT @F
@@:
ENDM
Outp MACRO Port, Reg ; Used to FORCE a delay after I/O
Out Port, Reg
Jmp SHORT @F
@@:
ENDM
IRQMapH Equ 20h SHR 2 ; Rom set mapped address
IRQMap Equ 1E0h ; Linear Address of 8259 IRQ Mapping
IRQMapB Equ IRQMap SHR 2 ; Bits to direct the 8259 to Linear Map
NumIRQ Equ 8 ; Number of IRQ Masks
Org 80h ; Data storage for Local USE
Stat Db ? ; Video Status Byte
;----------------------------------------------------------------------------
; The following EQUs define the status Byte
;
MDA Equ 80h ; Monochrome
CGA Equ 40h ; Color Graphics Adapter
EGA Equ 20h ; Enhanced Graphics Adapter
VGA Equ 10h ; Video Graphics Array
TwoMonitors Equ 08h ; A second video Adapter was found
TimeAct Equ 04h ; S = 8259 PIC is remapped
; R = 8259 PIC in normal mode
Enabled Equ 02h ; S = Screen is ACTIVE
; R = Screen is DISABLED
Quicky Equ 01h ; S = Resident code to blank video
; R = Normal Timer Checks
Second Equ 01h ; S = Found Resident Code
; R = No Resident code found
Stat1 Db ? ; Used for Second adapter Identifier
Click Equ 10h ; S = Do a KeyClick with KeyMake
; R = No KeyClick
CtrlOn Equ 08h ; Control Key has been pressed
EscOn Equ 04h ; The ESC key has been pressed
EnterOn Equ 02h ; The Enter Key has been pressed
CtrlKey Equ 1Dh ; Scan code for the CTRL Key
EnterKey Equ 1Ch ; Scan code for the Enter key
EscKey Equ 01h ; Sacn Code for the ESC Key
MSR Dw ? ; MSR for primary Adapter
MSR1 Dw ? ; MSR for seconf adapter
TimerTic Dw ? ; Timer Tic Counter
UsrTic Dw ? ; Usr set maximum
OneMin Equ 1092 ; One minute of TICS
FiveMins Equ OneMin*5 ; Five minutes of TICS
MaxMin Equ 9 ; Nine maximum minutes
MaxTics Equ OneMin*MaxMin ; Nine minutes maximum time allowed
MSRV Db 8 DUP (?) ; Video - MSR enable values
OldInt8 Dd ? ; Original INT Vector
CPUType Dw ? ; Type of CPU - 86/286/386
NDPType Dw ? ; Type of NDP - 87/287/387
Org 100h ; Start of Logic
Main PROC FAR
ASSUME Cs:@code, Ds:@code, Es:@code
Machine LABEL BYTE
Jmp Init ; Do the Initialization
Signature Db 'BLANK V1.0 - April 1, 1989',0
SigLen Equ $-Signature ; Character size
NewLLInt PROC NEAR
GoInt 8
GoInt LLInt9 ; Jump to the IRQ 1 Handler - KEYPRESS
GoInt 10
GoInt 11
GoInt 12
GoInt 13
GoInt 14
GoInt 15
LLInt9:
Cli ; Disable INTR
Push Ax ; Save registers
Push Bx
Push Cx
Push Dx
Push Ds
Push Cs ; Set local coverage
Pop Ds
Inp Al,60h ; Read the KBD
Test Al,80h ; Is this KEY Release
Jnz ChkCtrl ; Yes - Then Skip the CLICK
Test Stat1,Click ; Do a KeyClick
Jz ChkCtrl ; No
Push Ax ; Save Byte
Mov Al,0BFh ; Set clock rate
Outp 43h,Al ; for clock 2
Mov Al,04Bh
Outp 42h,Al
Mov Al,0Fh
Outp 42h,Al
Inp Al,61h ; read the port
Mov Ah,Al ; save data for restore
Or Al,3h ; enable the speaker gate
Outp 61h,Al
Mov Cx,100h ; Set TIME for GATE 2 Open
@@:
Loop @B ; loop to myself
Mov Al,Ah ; restore data
Outp 61h,Al
Pop Ax ; Restore Byte
ChkCtrl:
Cmp Al,CtrlKey ; Is this The Control Key ?
Jnz ChkEsc ; No - Check for the ESC Key
Or Stat1,CtrlOn ; Set the Control Key has been Pressed
Jmp SHORT ClearCtr ; Now check the Screen TIMEOUT
ChkEsc:
Cmp Al,EscKey ; IS this the ESC Key
Jnz ChkClick ; No - Check for Click Toggle
Or Stat1,EscOn ; Set ESC has been pressed
Jmp SHORT ClearCtr ; Ok - now clear the counter
ChkClick:
Cmp Al,EnterKey ; Click Toggle Key
Jnz ClearKeys ; No
Or Stat1,EnterOn ; Yes - then set for check
Jmp SHORT ClearCtr ; Now clear the TIMER Count
ClearKeys:
And Stat1,NOT (EscOn OR CtrlOn OR EnterOn)
ClearCtr:
Xor Ax,Ax ; Ok, Key was pressed - Clear
Mov TimerTic,Ax ; the counter
Mov Al,Stat1 ; Get the Status Byte
And Al,EscOn OR CtrlOn
Cmp Al,EscOn OR CtrlOn ; Is this a QUICK Blank?
Jnz Chain9 ; No - then Exit
Or Stat,Quicky ; Set for Quick Blank Of the Video
Xor Stat1,Quicky ; Reset BIT
IgnoreKey:
Mov Al,0E1h ; Ack 8259 For IRQ1
Outp 20h,Al ; Send the Ack
Inp Al,61h ; Now reset the KBD
Mov Ah,Al ; Save current Status
Or Al,80h ; Enable sensw
Outp 61h,Al
Mov Al,Ah ; Restore Status
And Al,7Fh ; Enable KBD
Outp 61h,Al
Pop Ds ; Restore registers
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Iret
Chain9:
Mov Al,Stat1 ; Get the Status Byte
And Al,CtrlOn OR EnterOn
Cmp Al,CtrlOn OR EnterOn ; Is this a Click Toggle
Jnz Chain91 ; No - then Check QUICK Blank
Xor Stat1,Click ; Toggle Click'ing
Jmp IgnoreKey ; Ignore the KeyMake
Chain91:
Test Stat1,Quicky ; In QUICK BLANK Mode
Jnz IgnoreKey ; Yes - then Exit
Test Stat,Enabled ; Is the Screen Active
Jnz LLIExit ; Yes - then pass to next
Test Stat,EGA OR VGA ; Enhanced videos
Jz DoMDCGA ; No
Mov Al,20h ; Enable the EGA/VGA
Call DoEVGA
Jmp SHORT LLI9Exit1 ; and get out
DoMDCGA:
Push Ds ; Save
Xor Ax,Ax ; Set to SEG=0
Mov Ds,Ax
Mov Al,Ds:[449h] ; Get Current Mode
Pop Ds ; Restore
Mov Dx,MSR ; Get the primary MSR
Lea Bx,MSRV ; Point to Xlate table
Xlat MSRV ; Translate to proper enable Value
Outp Dx,Al ; VIDEO IS NOT ACTIVE
LLI9Exit1:
Mov Al,29h ; Set for Enable
Call Adapter2 ; Enable it if present
Or Stat,Enabled ; Display is now active
LLIExit:
Pop Ds ; Restore registers
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Int 9 ; CHAIN to INT 9
Iret
NewLLInt ENDP
NewInt8 PROC NEAR
Sti ; Enable INTR
Pushf ; fake INTR to chained links
Call DWORD PTR Cs:OldInt8
Cmp Ax,-1 ; Check for Chained Load Checking
Jnz NewInt81 ; Noop
Cmp Bx,-2 ; Check Again
Jnz NewInt81 ; Noop
Cmp Cx,-3 ; Check again
Jnz NewInt81 ; Noop
Cmp Dx,-4 ; This should be enough Checking
Jnz NewInt81 ; Noop
Push Cs ; Must Reture Segment in ES
Pop Es
Jmp SHORT I8Exit ; Back to Caller
NewInt81:
Test Cs:Stat,TimeAct ; Are we disabled
Jnz Update ; No then update the counter
I8Exit:
Iret ; Just Exit
Update:
Push Ax ; Save registers
Push Bx
Push Dx
Push Ds
Push Cs
Pop Ds ; Get Local Coverage
Test Stat,Quicky ; Perform a QUICKY?
Jz NormTime ; No
And Stat,NOT Quicky ; Clear BIT
Jmp SHORT QuickBlank; Do it FRED
NormTime:
Test Stat,Enabled ; is the screen active
Jz TExit ; No - then do not check
Inc TimerTic ; Add to counter
Mov Ax,TimerTic ; have we reachewd our limit?
Cmp Ax,UsrTic ; Get usr set maximum
Jb TExit ; No - then Exit
QuickBlank:
And Stat,NOT Enabled; set disabled
Test Stat,EGA OR VGA ; is this an EGA/VGA
Jnz DoSpecial ; Yes
Mov Dx,MSR ; Get the Primary MSR
Mov Al,25h ; Disable for MDA/CGA
Outp Dx,Al
Jmp SHORT TExit1 ; Set screen is disabled
DoSpecial:
Xor Al,Al ; Disable the EVGA
Call DoEVGA ; Blank out the EGA/VGA Screen
TExit1:
Mov Al,25h ; Set Disable Code
Call Adapter2 ; Check for second adapter
TExit:
Pop Ds ; Restore registers
Pop Dx
Pop Bx
Pop Ax
Jmp I8Exit ; Back to the shadows
NewInt8 ENDP
DoEVGA PROC NEAR
Push Ax ; Save Command code
Push Ds ; Save DS
Xor Ax,Ax ; set to segment = 0
Mov Ds,Ax
Mov Al,Byte Ptr Ds:[465h] ; Get current 6845 MSR value
Mov Bx,Word Ptr Ds:[463h] ; Get current CRT I/O Port
Pop Ds ; Restore Coverage
Add Bx,6 ; Set to Status Register
Mov Dx,3CDh ; Assume EGA for now
Inp Al,Dx
Mov Ah,Al ; Save current video State
And Al,67h
Outp Dx,Al
Mov Dx,Bx ; Set to Current CRT IO Port
Inp Al,Dx ; Read current video Status
Pop Bx ; Restore Function 0=Disable 20=Enable
Mov Al,Bl
Mov Dx,3C0h ; Video Attributes Register
Outp Dx,Al ; BLANK THE SCREEN
Mov Al,Ah ; Restore CRT Status
And Al,0EFh ; Strip off Bit 5
Mov Dx,3CDh
Outp Dx,Al
Ret ; Back to the caller
DoEVGA ENDP
Adapter2 PROC NEAR
Test Stat,TwoMonitors; Do we have 2 videos
Jz A2Exit ; No - then Exit
Mov Dx,MSR1 ; Get MSR for secondary Adapter
Outp Dx,Al ; Send command
A2Exit:
Ret
Adapter2 ENDP
Init: ; Initialization Routine
Mov Ax,Cs ; Ensure DOS covers us on initialization
Mov Ds,Ax
Mov Es,Ax
Lea Dx,Message ; Display ownership message
Mov Ah,9
Int 21h
Push Es
Mov Ax,0F000h ; Get machine type ID
Mov Es,Ax
Mov Al,Byte Ptr Es:[0FFFEh]
Pop Es
Mov Machine,Al ; Save Machine ID
; Initialize parameters
Lea Si,Stat ; Point to the Parameter Table
Cmp Byte Ptr [Si],0 ; Check for any parameter value
Jz Default ; Ok - use default
Inc Si ; Bump to the first character
ParmIn:
Lodsb ; Get parameter count
Cmp Al,20h ; Is this a space
Jz ParmIn ; Yes - then ignore
Cmp Al,9h ; Is this a TAB
Jz ParmIn ; Yes - then SKIP it
Cmp Al,0Dh ; End of Input
Jz Default ; Yes - then use default value
Xor Al,30h ; Strip off ASCII
Cbw ; Strip upper half of word
Or Al,Al ; Anything Passed
Jz ChkDis ; No - then check for disable
Cmp Al,MaxMin ; Above Maximum
Ja Default ; To high - set default
Jmp SHORT SetTime ; Calculate TICS
ChkDis:
Call CheckMap ; Are we already resident - ES has Res Vector
Jc NoGo ; Can not disable - not loaded
Call GetCpu ; Get CPU Type
Mov CPUType,Ax ; And save
Call GetNdp ; Get NDP if any
Mov NDPType,Ax ; And Save
And Es:Stat,NOT TimeAct ; Set disable switch
Mov Bl,IRQMapH ; Set Vector for 8259
Call SetMap ; Remap the 8259
Sti ; Enable INTR
Lea Dx,Disabled ; Show Disabled
Mov Ah,9
Int 21h
Norm:
Mov Ax,4C00h ; Terminate normally
Int 21h
NoGo:
Lea Dx,NotLoaded ; We are not loaded
Mov Ah,9
Int 21h
Term:
Mov Ax,4C01h ; Exit with error
Int 21h
SetTime:
Mov Cx,OneMin ; Get TICS per minute
Mul Cx ; Convert to TICS
Jmp SHORT SetTICS ; Save off tics wanted
Default:
Mov Ax,FiveMins ; Set default to FIVE Minutes
SetTICS:
Mov UsrTic,Ax ; Save in local storage
Mov TimerTic,0 ; Initialize Current TIC Counter
Mov Stat,0
Mov Stat1,0
Call GetCpu ; Get CPU Type
Mov CPUType,Ax ; And save
Call GetNdp ; Get NDP if any
Mov NDPType,Ax ; And Save
Lea Di,MSRV ; Point to Local storage
Lea Si,MSRValues ; Table of NSR Values
Mov Cx,LenMSRV ; Get count
Rep Movsb ; Copy to local storage
Lea Di,WorkBuf ; Point to Storage Area
Xor Bx,Bx ; Clear for Call
Mov Ax,1B00h ; Check for a VGA
Int 10h ; Video BIOS call
Cmp Al,1Bh ; Is this a VGA
Jnz ChkEGA ; No - then check for other
Mov Al,VGA ; Set for VGA
Jmp SHORT SetVideo ; now - mov the local to resident
ChkEGA:
Mov Ah,12h ; EGA Status check
Mov Bl,10h
Xor Cx,Cx ; Clear the status bits
Int 10h ; Video BIOS Call
Jcxz NoEGA ; Now check for MDA/CGA
Mov Al,EGA ; Set for EGA
Jmp SHORT SetVideo ; Set video type
NoEGA:
Mov Ah,0Fh ; Get Current Video Mode
Int 10h
Cmp Al,7 ; Is a monochrome?
Je SetMono ; Yes
Cmp Al,15 ; Graphic Mono
Je SetMono ; Yes
Mov Al,CGA ; no - its a CGA
Mov Dx,3D8h ; Set CGA MSR
Jmp SHORT SetVideo ; Save in local storage
SetMono:
Mov Al,MDA ; Set for Mono
Mov Dx,3B8h ; Set MONO MSR
SetVideo:
Mov Stat,Al ; Set type of Video
Mov MSR,Dx ; Save for Resident code
;----------------------------------------------------------------------------
; Determine if a second video adapter is present
Mov Dx,3D4h ; Assume CGA attached
Push Ds ; Save
Xor Ax,Ax ; Clear
Mov Ds,Ax ; Set SEG=0
Cmp Dx,Ds:[463h] ; Is this a CGA ?
Pop Ds ; Restore
Jnz Save_Second ; No - then already set for CGA
Mov Dx,3B4h ; Yes, look for MDA
Save_Second:
Mov Al,0Fh ; Select cursor low
Outp Dx,Al
Inc Dx ; Get initial value for reset
Inp Al,Dx
Mov Ah,Al ; And save it
Find_Second:
Mov Al,55h ; Write first pattern
Outp Dx,Al
Inp Al,Dx ; Read pattern back
Cmp Al,55h ; Is pattern same?
Jnz No_Second ; No, adapter not there
Mov Al,0AAh ; Write second pattern
Outp Dx,Al
Inp Al,Dx ; Read pattern back
Cmp Al,0AAh ; Is pattern same?
Jnz No_Second ; No, adapter not there
Mov Cl,TwoMonitors ; Yes, set status bits
Jmp SHORT GSADone ; Finished
No_Second:
Xor Cl,Cl ; Sorry, but you only have ONE monitor
GSADone:
Mov Al,Ah ; Restore cursor info
Outp Dx,Al
Add Dx,3 ; Set to MSR of appropriate monitor
Or Stat,Cl ; Save 2nd monitor info
Or Cl,Cl ; Check if found for message display
Jz CopyStorage
Cmp Dx,3D8h ; Is the Monitor a CGA
Jz TwoCGA ; Yes
Or Stat1,MDA ; No Second monitor is a MDA
Jmp SHORT TwoShow
TwoCGA:
Or Stat1,CGA ; Set 2nd adapter is a CGA
TwoShow:
Mov MSR1,Dx ; Save MSR
Lea Dx,TwoMons ; Point to the messgae
Mov Ah,9
Int 21h
CopyStorage:
Mov Ax,UsrTic ; Get the number of TICS
Mov Cx,OneMin ; Number of tics per minute
Xor Dx,Dx ; Clear for Divide
Div Cx
Or Al,30h ; Make ASCII
Mov Minute,Al ; Svae in the string
Lea Dx,TimeOut
Mov Ah,9
Int 21h
;-----------------------------------------------------------------------------
; Now we must check to see if we are already Resident or not.
; If we are, then the new Timer value is passed to the resident code.
; Note - A value of ZERO will Disable the BLANK Program
;
Call CheckMap ; Check for Loaded Status
Jc ReVector ; Not loaded - Must revector
Mov Al,Stat ; Get Current Status and pass to res code
Mov Es:Stat,Al
Mov Ax,MSR ; Pass Current MSR to Res Code
Mov Es:MSR,Ax
Mov Ax,MSR1 ; Secondary MSR to Res Code
Mov Es:MSR1,Ax
Xor Ax,Ax ; Clear current Count
Mov Es:TimerTic,Ax
Mov Ax,UsrTic ; Get the New TICS
Mov Es:UsrTic,Ax ; and put into the resident code
Mov Stat,Second ; And save in local
Jmp SHORT ReMap ; No - then setup 8259 PIC mapping
PassTic:
Lea Dx,ParmPass ; Set parameters Passed
Mov Ah,9
Int 21h
Jmp Norm ; And Exit
ReVector:
Mov Ax,3508h ; Get INT 8 Vector
Int 21h
Cli
Mov Word Ptr OldInt8 +0,Bx ; Save offset
Mov Word Ptr OldInt8 +2,Es ; Save segment
Sti
Lea Dx,NewInt8 ; Point to My Handler
Mov Ax,2508h ; Set INT VEctor
Int 21h ; Now legal with DOS
Xor Ax,Ax ; Set to Segment 0
Mov Ds,Ax
Mov Si,IRQMap ; Get MAP address
Mov Ax,OFFSET NewLLInt ; Address of my coding
Mov Cx,NumIRQ ; Set Loop Counter
Cli ; Ok Disable INTR
IRQLoop:
Mov [Si + 0],Ax ; Address of IRQ offset
Mov [Si + 2],Cs ; Address of IRQ segment
Add Ax,3 ; Point to the Next IRQ Mask Handler
Add Si,4 ; Bump to Next IRQ Address
Loop IRQLoop ; Finish the Masks
ReMap:
Mov Ax,Cs ; Restore Local Coverage
Mov Ds,Ax
Mov Bl,IRQMapB ; Set 8259 Vector Address
Call SetMap ; Map the 8259
Test Stat,Second ; Is this for already resident code
Jz NewLoad ; No
Or Es:Stat,TimeAct OR Enabled
Jmp PassTic ; Exit normal
NewLoad:
Or Stat,TimeAct OR Enabled ; Set initial status
Or Stat1,Click ; Set KeyClick on KeyMake
Lea Dx,ResMsg ; Show resident message
Mov Ah,9
Int 21h
Lea Dx,Init + 15 ; Address of End of Resident Code
Mov Cl,4
Shr Dx,Cl
Mov Ax,3100h
Int 21h
CheckMap PROC NEAR
Xor Ax,Ax ; Get segment 0 Coverage
Mov Ds,Ax
Les Bx,DWORD PTR Ds:[IRQMap]
Push Cs ; Restore local coverage
Pop Ds
Lea Si,Signature ; Point to My Signature
Mov Di,Si ; Should be the same in resident Coding
Mov Cx,SigLen ; how many characters for compare
Repz Cmpsb ; Is this My coding
Jnz NotMe ; Not me
Clc ; Set mapping was found
Ret ; And exit
NotMe:
Mov Ax,Es ; Check for Zeor segment
Or Ax,Ax ; to see if anyone else has this INterrupt
Jz NotMe1 ; No one else found
Push Cs ; For compare when return from INT
Pop Es
Mov Ax,-1 ; Setup for internal checking
Mov Bx,-2
Mov Cx,-3
Mov Dx,-4
Int 8 ; Use the Normal H/W Timer
Mov Ax,Cs
Mov Bx,Es
Or Ax,Bx ; Is this Us
Jz NotMe1 ; No exit
Clc ; Yes - then ES =
Ret
NotMe1:
Stc ; We are not loaded
Ret ; Back to caller
CheckMap ENDP
SetMap PROC NEAR
Cli
Inp Al,21h ; Get Curent IMR
Push Ax ; And save for a restore
Mov Al,0FFh
Outp 21h,Al
Mov Cl,Machine ; Get the Machine ID
Cmp Cl,0F8h ; Model 80
Jz SetMap2 ; Yes - has 2 8259s
Cmp Cl,0FCh ; AT Type?
Jz SetMap2 ; Yes - has 2 8259s
Mov Al,13h ; Set ICW1
Outp 20h,Al ; Init the 8259
Mov Al,Bl ; Get ReMapped Address
Outp 21h,Al ; Set New Address
Mov Al,9h ; Skip the ICW3 and DO ICW4
Outp 21h,Al ; The 8259 is remapped
Jmp SHORT SMExit ; Now exit
SetMap2:
Mov Al,11h ; Set ICW1 for MASTER/SLAVE Mode
Outp 20h,Al ; To set IRQ address into My Coding
Mov Al,Bl ; Remapped Address
Outp 21h,Al ; ICW2 - Vectored Address from BL
Mov Al,4h ; ICW3 - Set Slave Mapped to IR2 on Master
Outp 21h,Al
Mov Al,1 ; OCW4 - Set 8259 PIC to iAPX86/88 Mode
Outp 21h,Al
SMExit:
Pop Ax ; Restore Original Mask - IMR
Outp 21h,Al ; And reset the mask bits
Sti
Ret ; Back to Caller
SetMap ENDP
GetCpu PROC NEAR
Pushf ; Save FLAG registers
Xor Ax,Ax ; Clear AX and push onto the stack.
Push Ax
Popf ; Pop a zero into FLAGs register
Pushf ; Attempt to set bit 12-15 to a zero
Pop Ax ; Recover FLAG word
And Ax, 0F000h ; If Bits 12-15 are set then the processor
Cmp Ax, 0F000h ; is an 8018x or an 808x
Jz is801x
Mov Ax,0F000h ; Try to set FLAG bits 12-14 (NT, IOPL)
Push Ax
Popf ; put 07000H into flags
Pushf
Pop Ax
And Ax,0F000h ; if bits 12-14 are cleared then the
Jz is80286 ; processor is an 286
is80386: ; Else it is a 386
Mov Ax,386h
Jmp Short GCExit ; Exit
is80286:
Mov Ax,286h ; return 286 in AX
Jmp Short GCExit ; Get Out
is801x: ; It is a 8086, a 80186, or a V20/V30
Mov Ax,0FFFFh ; Set AX to all 1s
Mov Cl,33 ; Will shift it 33 times if it is an
; 808x, or 1 time if it is an 8018x.
Shl Ax,Cl ; If we shift 33 times all bits are
Jnz is80186 ; zero. If any bits are on it's an 18x
is8086: ; Else we have an 8086 or V20/V30.
Xor Al,Al ; Sets ZF
Mov Al,40h ; 64 decimal
Mul Al ; 64**2 > 255
Jz isv30 ; V20/V30 MUL leaves ZF untouched
; 8086 ZF==OF after MUL
Mov Ax,86h ; Return 86/V20
Jmp Short GCExit
isv30:
Mov Ax,30h ; Return V30
Jmp Short GCExit
is80186:
Mov Ax,186h ; Return 186
GCExit:
Popf ; Restore flags
Ret
GetCpu ENDP
ControlB Equ Byte Ptr [Bp - 2]
ControlW Equ Word Ptr [Bp - 2]
GetNdp PROC NEAR
Push Bp ; Setup local storage
Mov Bp,Sp
Mov ControlW,0 ; Initialize storage
Fninit ; try to initialize NDP
Fnstcw ControlW ; put control word in mem
Mov Ah,ControlB ; if AH is 03h, you got
Cmp Ah,03h ; an NDP on board !!
Jz Chk87 ; found somethin', keep goin'
Xor Ax,Ax ; no processor found
Jmp Short NdpExit ; retunr
Chk87:
And ControlW,NOT 0080h ; turn ON interrupts (IEM=0)
Fldcw ControlW ; load control word
Fdisi ; turn OFF interrupts (IEM=1)
Fstcw ControlW ; store control word
Test ControlB,80h ; iff IEM=1, 8087
Jz Chk287 ; guess not! March on....
Mov Ax,87h ; this is an 8087
Jmp Short NdpExit
Chk287:
Finit ; set default infinity mode
Fld1 ; make infinity
Fldz ; by dividing
Fdiv ; 1 by zero !!
Fld St ; now make a
Fchs ; negative infinity
Fcompp ; compare Ur two infinities
Fstsw ControlW ; if, for 8087 or 80287
Fwait ; til status word is put away
Push Ax ; save
Mov Ax,ControlW ; get control word
Sahf ; put AH into flags
Pop Ax
Jnz is80387 ; NO GOOD.... march on !!
Mov Ax,287h ; set 80287
Jmp Short NdpExit
is80387:
Mov Ax,387h ; must be an 80387
NdpExit:
Pop Bp ; Restore Stack
Ret ; back to shadow
GetNdp ENDP
MSRValues Db 2Ch, 28h, 2Dh, 29h, 2Ah, 2Eh, 1Eh, 2Ch
LenMSRV Equ $-MSRValues
Message Db 13,10
Db 9,' Blank v1.2 - By Richard Wissinger - April 1989',13,10,'$'
ResMsg Db 9,9,' Resident portion of Blank loaded',13,10,'$'
TwoMons Db 9,9,' A second video adapter was found',13,10,'$'
ParmPass Db 9,9,' New time passed to resident code',13,10,'$'
TimeOut Db 9,9,' Screen timeout set for '
Minute Db '5 minutes',13,10,'$'
NotLoaded Db 9,7,' Blank could not be found in resident memory!',13,10,'$'
Disabled Db 9,9,' Resident Blank has been disabled',13,10,'$'
WorkBuf Equ $ ; Work area for Video BIOS 1B/12
Main ENDP
END Main